#ifndef __MY_DATA__
#define __MY_DATA__
#include <unordered_map>
#include <pthread.h>
#include "util.hpp"
#include "config.hpp"

namespace cloud
{
    typedef struct BackupInfo
    {
        bool pack_flag; // 文件是否被压缩标志
        size_t fsize; // 文件大小
        time_t mtime; // 文件最后一次修改时间
        time_t atime; // 文件最后一次访问时间
        std::string real_path; // 文件实际存储路径
        std::string pack_path; // 压缩包存储路径
        std::string url; // 文件访问URL
        bool NewBackupInfo(const std::string &realpath)
        {
            FileUtil fu(realpath);  
            if(fu.Exists() == false) 
            {
                std::cout << "new backupinfo: file not exit" << std::endl;
                return false;
            }
            Config* config = Config::GetInstance();
            std::string packdir = config->GetPackDir();
            std::string packsuffix = config->GetPackFileSuffix();
            std::string download_prefix = config->GetDownloadPrefix();
            pack_flag = false;
            fsize = fu.FileSize();
            mtime = fu.LastMtime();
            atime = fu.LastATime();
            real_path = realpath;
            pack_path = packdir + fu.FileName() + packsuffix;
            url = download_prefix + fu.FileName();
            return true;
        }
    }BackupInfo;
    class DataManager
    {
    public:
        DataManager() 
        {
            _backup_file = Config::GetInstance()->GetBackupFile(); // 获取备份信息持久化存储的文件
            pthread_rwlock_init(&_rwlock, NULL); // 初始化读写锁
            InitLoad(); // 初始化加载
        }
        ~DataManager()
        {
            pthread_rwlock_destroy(&_rwlock); // 释放读写锁
        }
        bool Insert(const BackupInfo &info)
        {
            pthread_rwlock_wrlock(&_rwlock);
            _table[info.url] = info;
            pthread_rwlock_unlock(&_rwlock);
            Storage();
            return true;
        }
        bool Updata(const BackupInfo &info)
        {
            pthread_rwlock_wrlock(&_rwlock);
            _table[info.url] = info;
            pthread_rwlock_unlock(&_rwlock);
            Storage();
            return true;
        }
        bool GetOneByURL(const std::string &url, BackupInfo* info)
        {
            pthread_rwlock_wrlock(&_rwlock);
            auto it = _table.find(url);
            if(it == _table.end())
            {
                pthread_rwlock_unlock(&_rwlock);
                return false;
            }
            *info = it->second;
            pthread_rwlock_unlock(&_rwlock);
            return true;
        }
        bool GetOneByRealpath(const std::string &realpath, BackupInfo* info)
        {
            pthread_rwlock_wrlock(&_rwlock);
            auto it = _table.begin();
            for(; it != _table.end(); ++it)
            {
                if(it->second.real_path == realpath)
                {
                    *info = it->second;
                    pthread_rwlock_unlock(&_rwlock);
                    return true;
                }
            }
            pthread_rwlock_unlock(&_rwlock);
            return false;
        }
        bool GetAll(std::vector<BackupInfo>* array)
        {
            pthread_rwlock_wrlock(&_rwlock);
            auto it = _table.begin();
            for(; it != _table.end(); ++it)
            {
                array->push_back(it->second);
            }
            pthread_rwlock_unlock(&_rwlock);
            return true;
        }
        bool Storage()
        {
            // 1.获取所有数据
            std::vector<BackupInfo> array;
            GetAll(&array);
            // 2.添加到Json::Value中
            Json::Value root;
            for(int i = 0; i < array.size(); i++)
            {
                Json::Value item;
                root["pack_flag"] = array[i].pack_flag;
                root["fsize"] = (Json::Int64)array[i].fsize;
                root["atime"] = (Json::Int64)array[i].atime;
                root["mtime"] = (Json::Int64)array[i].mtime;
                root["real_path"] = array[i].real_path;
                root["pack_path"] = array[i].pack_path;
                root["url"] = array[i].url;
                root.append(item); // 添加数组元素
            }
            // 3.对Json::Value序列化
            std::string body;
            JsonUtil::Serialize(root, &body);
            // 4.写文件
            FileUtil fu(_backup_file);
            fu.SetContent(body);
            return true;
        }
        bool InitLoad()
        {
            // 1.将数据从文件中读取出来
            FileUtil fu(_backup_file);
            if(fu.Exists() == false)
            {
                return true;
            }
            std::string body;
            fu.GetContent(&body);
            // 2.反序列化
            Json::Value root;
            JsonUtil::Unserialize(body, &root);
            // 3.将反序列化得到的Json::Value中的数据添加到table中
            for(int i = 0; i < root.size(); i++)
            {
                BackupInfo info;
                info.pack_flag = root[i]["pack_flag"].asBool();
                info.fsize = root[i]["fsize"].asInt64();
                info.atime = root[i]["atime"].asInt64();
                info.mtime = root[i]["mtime"].asInt64();
                info.pack_path = root[i]["pack_path"].asString();
                info.real_path = root[i]["real_path"].asString();
                info.url = root[i]["url"].asString();
                Insert(info);
            }
            return true;
        }
    private:
        std::string _backup_file; // 备份信息持久化存储
        pthread_rwlock_t _rwlock; // 读写锁
        std::unordered_map<std::string, BackupInfo> _table; // 数据信息组织
    };
}
#endif
